/**
 * 
 */
package cz.cuni.mff.abacs.burglar.logics.objects.agents;

import cz.cuni.mff.abacs.burglar.logics.DataMap;
import cz.cuni.mff.abacs.burglar.logics.objects.BaseInterface;
import cz.cuni.mff.abacs.burglar.logics.objects.Room;
import cz.cuni.mff.abacs.burglar.logics.objects.items.Inventory;
import cz.cuni.mff.abacs.burglar.logics.objects.items.Item;
import cz.cuni.mff.abacs.burglar.logics.objects.items.Key;
import cz.cuni.mff.abacs.burglar.logics.objects.positions.Lockable;
import cz.cuni.mff.abacs.burglar.logics.objects.positions.Position;
import cz.cuni.mff.abacs.burglar.logics.objects.positions.Vender;
import cz.cuni.mff.abacs.burglar.logics.planning.instructions.Instruction;
import java.util.List;


/** 
 * Interface of the moving elements of the game.
 * 
 * Can be guards, burglars, dogs...
 * @author abacs
 *
 */
public interface Agent extends BaseInterface, Inventory {
	
		
	/** 
	 * State of agents. 
	 * 
	 * WELL means active, STUNNED means immobilized.
	 */
	public enum State {WELL, STUNNED};
	
	
	// -------------------------------------------------------------------------
	
	
	/**
	 * Returns the position where the agent is standing.
	 */
	public Position getPosition();
	
	
	/**
	 * Returns the identifier of the current position.
	 */
	public int getPositionId();
	
	
	/**
	 * Places the agent to the selected position.
	 * 
	 * @param walkableId identifier of the position.
	 */
	public void setPosition(int walkableId);
	
	
	/**
	 * Places the agent to the selected position.
	 */
	public void setPosition(Position walkable);
	
	
	// -------------------------------------------------------------------------
	
	
	/**
	 * Controls the state of the agent.
	 */
	public boolean isInState(State state);
	
	
	/**
	 * Returns the state of the agent.
	 */
	public State getState();
	
	
	/**
	 * Immobilizes the agent (state change).
	 */
	public void daze();
	
	
	// -------------------------------------------------------------------------
	
	
	/**
	 * Positions the agent to the selected place.
	 * 
	 * If the user enters a new room, it also looks around in the new room.
	 * 
	 * It also examines the position if it is a door.
	 * 
	 * @param stepable movement aim
	 * @return true if the move was successful.
	 */
	public boolean moveTo(Position stepable);

	
	/**
	 * Opens a container or door.
	 * 
	 * It also examines the position.
	 * 
	 * @return success indicator
	 */
	public boolean open(Lockable lockable);
	
	
	/**
	 * closes a container or door.
	 * 
	 * It also examines the position.
	 * 
	 * @return success indicator
	 */
	public boolean close(Lockable lockable);
	
	
	/**
	 * Unlocks a container or door if the agent possesses the relevant key.
	 * 
	 * It also examines the position.
	 * 
	 * @return success indicator
	 */
	public boolean unlock(Lockable lockable, Key key);
	
	
	/**
	 * Locks a container or door if the agent possesses the relevant key.
	 * 
	 * It also examines the position.
	 * 
	 * @return success indicator
	 */
	public boolean lock(Lockable lockable, Key key);
	
	
	/**
	 * Picks up the selected item from a container or other agent's inventory.
	 * 
	 * It also examines the position.
	 * 
	 * @return success indicator
	 */
	public boolean pickUp(Inventory inventory, Item item);
	
	
	/**
	 * Uses the selected object.
	 * 
	 * It also examines the position.
	 * 
	 * @param vender
	 * @return success indicator
	 */
	public boolean use(Vender vender);
	
	// -------------------------------------------------------------------------
	
	
	/**
	 * Returns the location of the agent.
	 * 
	 * @return room object
	 */
	public Room getRoom();
	
	
	/**
	 * Returns the location of the agent.
	 * 
	 * @return room identifier
	 */
	public int getRoomId();
	
	
	/**
	 * Controls the location of the agent.
	 */
	public boolean isInRoom(Room room);
	
	
	/**
	 * Controls the location of the agent.
	 */
	public boolean isInRoom(int roomId);
	
	
	/**
	 * Looks around in room, discovers new positions or details of them.
	 * 
	 * If the positions were already known, it does not change them.
	 * 
	 * @return true if something new was seen.
	 */
	public boolean lookAround();
	
	
	/**
	 * Agent examined from a distance.
	 * 
	 * @return copy of the agent.
	 */
	public Agent examinedFromFar();
	
	
	/**
	 * Returns whether the object matches another one from a distance.
	 * 
	 * @return whether the object matches another one from a distance.
	 */
	public boolean matchesFromFar(Agent agent);
	
	
	// -------------------------------------------------------------------------
	// instructions:
	
	
	/**
	 * Adds a new instruction to the end of the agent's instruction list.
	 */
	public void addInstruction(Instruction instruction);
	
	
	/**
	 * Adds multiple instructions to the end of the agent's instruction list.
	 */
	public void addInstructions(List<Instruction> instructions);
	
	
	/**
	 * Empties the agent's instruction list.
	 */
	public void clearInstructions();
	
	
	/**
	 * Returns the instruction list for a selected agent.
	 */
	public List<Instruction> getInstructions();
	
	
	/**
	 * Controls the non-emptyness of the agent's instruction list.
	 */
	public boolean hasInstructions();
	
	
	/**
	 * Returns the first instruction for a selected agent.
	 * 
	 * It also removes the instruction from the list.
	 * 
	 * @return
	 */
	public Instruction popFirstInstruction();
	
	
	/**
	 * Returns the agent's beliefs.
	 */
	public BeliefBase getBeliefBase();
	
	
	/**
	 * Returns the agent's goals.
	 */
	public GoalBase getGoals();
	
	
	/**
	 * Replicates the changeable details of the selected agent.
	 */
	public void copyChangeables(Agent original);
	
	
	/**
	 * Creates a copy of itself with the selected reference map.
	 */
	public Agent copy(DataMap reference);
	
}
